#include "dht11.h"


//初始化DHT 
void DHT_Init(void)
{	 
 	GPIO_InitTypeDef  GPIO_InitStructure;
 	
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	 	//使能PB端口时钟
	
 	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_13;	
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 	//推挽输出
 	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 	GPIO_Init(GPIOB, &GPIO_InitStructure);				 		//初始化IO口
 	
	GPIO_SetBits(GPIOB,GPIO_Pin_11);						
	GPIO_SetBits(GPIOB,GPIO_Pin_12);
	GPIO_SetBits(GPIOB,GPIO_Pin_13);	
} 


//复位DHT11
void DHT_Rst(u8 io)	   
{                 
	DHT_IO_OUT(io); 					//SET OUTPUT
	GPIO_ResetBits(GPIOB,Pin(io));		//DQ=0
    delay_ms(20);    					//拉低至少18ms
    GPIO_SetBits(GPIOB,Pin(io));		//DQ=1 
	delay_us(30);     					//主机拉高20~40us
}


//等待DHT的回应
//返回1:未检测到DHT的存在
//返回0:存在
u8 DHT_Check(u8 io) 	   
{   
	u8 retry=0;
	DHT_IO_IN(io);//SET INPUT	 
    while (GPIO_ReadInputDataBit(GPIOB,Pin(io)) && retry<100)//DHT会拉低40~80us
	{
		retry++;
		delay_us(1);
	};	 
	if(retry>=100)return 1;
	else retry=0;
    while (!GPIO_ReadInputDataBit(GPIOB,Pin(io)) && retry<100)//DHT拉低后会再次拉高40~80us
	{
		retry++;
		delay_us(1);
	};
	if(retry>=100)return 1;	    
	return 0;
}


//从DHT读取一个位
//返回值：1/0
u8 DHT_Read_Bit(u8 io) 			 
{
 	u8 retry=0;
	while(GPIO_ReadInputDataBit(GPIOB,Pin(io))&&retry<100)//等待变为低电平
	{
		retry++;
		delay_us(1);
	}
	retry=0;
	while(!GPIO_ReadInputDataBit(GPIOB,Pin(io))&&retry<100)//等待变高电平
	{
		retry++;
		delay_us(1);
	}
	delay_us(40);//等待40us
	if( GPIO_ReadInputDataBit(GPIOB,Pin(io)))return 1;
	else return 0;		   
}
//从DHT11读取一个字节
//返回值：读到的数据
u8 DHT_Read_Byte(u8 io)    
{        
    u8 i,dat;
    dat=0;
	for (i=0;i<8;i++) 
	{
   		dat<<=1; 
	    dat|=DHT_Read_Bit(io);
    }						    
    return dat;
}
//从DHT11读取一次数据
//temp:温度值(范围:0~50°)
//humi:湿度值(范围:20%~90%)
//返回值：1,正常;0,读取失败
u8 DHT_Read_Data(u8 io,float *temp,float *humi)    
{        
 	u8 buf[5];
	u8 i;
	
	DHT_Rst(io);
	
	if(DHT_Check(io)==0)
	{
		for(i=0;i<5;i++)//读取40位数据
		{
			buf[i]=DHT_Read_Byte(io);
		}
		if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
		{
			*humi=buf[0]+buf[2]*0.1;
			if(buf[3]>>7 != 1)
			{
				*temp=buf[2]+(buf[3]&0x0f)*0.1;
			}
			else
			{
				*temp=0-(buf[2]+(buf[3]&0x0f)*0.1);
			}
			
		}
	}else return 0;
	return 1;	    
}



void DHT_IO_IN(u8 io)
{
 	GPIO_InitTypeDef  GPIO_InitStructure;
 	
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	 	//使能PB端口时钟
	
	GPIO_InitStructure.GPIO_Pin = Pin(io);			 	
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; 		 		//输入
 	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 	GPIO_Init(GPIOB, &GPIO_InitStructure);				 		//初始化IO口
}

void DHT_IO_OUT(u8 io)
{
 	GPIO_InitTypeDef  GPIO_InitStructure;
	
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	 	//使能PB端口时钟
	
 	GPIO_InitStructure.GPIO_Pin = Pin(io);			
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 	//推挽输出
 	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 	GPIO_Init(GPIOB, &GPIO_InitStructure);				 		//初始化IO口
}








